﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Design;
using System.Windows.Forms.Design;
using System.Windows.Forms;

namespace ProgNetComponents.Design.Editors
{
    /// <summary>
    /// Allows to select single value from list of available choices
    /// </summary>
    public abstract class BaseListEditor : UITypeEditor
    {
        protected IWindowsFormsEditorService _EditorService;
        protected Dictionary<string, object> _List;
        protected IServiceProvider _ServiceProvider;
        protected System.ComponentModel.ITypeDescriptorContext _Context;
        protected ListBox _ListBox;
        protected virtual bool SortItems
        {
            get { return true; }
        }
        protected virtual bool AlwaysGetValues
        {
            get { return true; }
        }
        
        public override bool IsDropDownResizable
        {
            get
            {
                return true;
            }
        }
        
        protected abstract Dictionary<string, object> GetListBoxItems();
        protected virtual ListBox CreateControl()
        {
            return new ListBox();
        }
        protected virtual void SetSelectedItems(object value)
        {
            if (_List != null)
            {
                foreach (KeyValuePair<string,object> kvp in _List)
                {
                    if (kvp.Value.IsTheSame(value))
                    {
                        _ListBox.SelectedItem = kvp.Key;
                        break;
                    }
                }
            }
        }
        protected virtual object GetSelectedValue()
        {
            if (_ListBox != null)
            {
                string key = _ListBox.SelectedItem.AsString();
                if (_List.ContainsKey(key))
                    return _List[key];
            }
            return null;
        }

        protected void CreateListBox()
        {
            if (_ListBox == null)
            {
                _ListBox = CreateControl();
                _ListBox.Sorted = SortItems;
                _ListBox.BorderStyle = BorderStyle.None;
                _ListBox.KeyDown += new KeyEventHandler(listBox_KeyDown);
                _ListBox.MouseDown += new MouseEventHandler(listBox_MouseDown);
                _List = GetListBoxItems();
                if (_List != null)
                {
                    foreach (string k in _List.Keys)
                        _ListBox.Items.Add(k);
                }
            }
            else
            {
                if (AlwaysGetValues)
                {
                    _ListBox.Items.Clear();
                    _List = GetListBoxItems(); 
                    if (_List != null)
                    {
                        foreach (string k in _List.Keys)
                            _ListBox.Items.Add(k);
                    }
                }
            }
        }

        protected void CloseDropDown()
        {
            if (_EditorService != null)
                _EditorService.CloseDropDown();
        }

        protected virtual void listBox_MouseDown(object sender, MouseEventArgs e)
        {
            CloseDropDown();
        }

        protected virtual void listBox_KeyDown(object sender, KeyEventArgs e)
        {
            CloseDropDown();
        }
        
        public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            _Context = context;
            _ServiceProvider = provider;
            _EditorService = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
            if (_EditorService != null)
            {
                CreateListBox();
                SetSelectedItems(value);
                _EditorService.DropDownControl(_ListBox);
                object val = GetSelectedValue();
                if (val == null)
                    val = value;
                return val;
            }
            return null;
        }

        public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.DropDown;
        }
        public override void PaintValue(PaintValueEventArgs e)
        {
            "public override void PaintValue(PaintValueEventArgs e)".Log();
            base.PaintValue(e);
        }
    }
}
